# -*- coding:utf-8 -*-
import os
import json
import time
import requests
import datetime
import traceback
from obs import ObsClient
from urllib.parse import urlparse
import http.client as httplib

from requests.packages.urllib3.exceptions import InsecureRequestWarning

requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

DEFAULT_CDN_LOG_URL = "https://cdn.myhuaweicloud.com/v1.0/cdn/logs"
page_size = 20


def handler(event, context):
    log = context.getLogger()
    dump_cdn_log_handler = DumpCDNLogHandler(context)
    try:
        dump_cdn_log_handler.run()
        return "Done"
    except:
        exec_info = traceback.format_exc()
        log.error(f"failed to dump cdn log to obs: {exec_info}")
        return f"failed to dump cdn log to obs: {exec_info}"
    finally:
        dump_cdn_log_handler.obs_client.close()


class DumpCDNLogHandler:

    def __init__(self, context):
        self.logger = context.getLogger()
        obs_endpoint = context.getUserData("obs_endpoint")
        self.obs_client = new_obs_client(context, obs_endpoint)
        self.target_bucket = context.getUserData("target_bucket")
        self.auth_token = context.getToken()
        self.cdn_log_url = context.getUserData('cdn_log_url',
                                               DEFAULT_CDN_LOG_URL)
        self.domainName = context.getUserData('domain_name')

    def run(self):
        yesterday = datetime.date.today() + datetime.timedelta(-1)
        query_date = yesterday.strftime("%Y-%m-%d")
        timestamp = int(time.mktime(yesterday.timetuple()) * 1000)

        page_number = 1
        retry_count = 0
        while True:
            result = self.pull_cdn_logs(timestamp, page_number)
            if result == "error" and retry_count < 3:
                retry_count += 1
                continue
            result_json = json.loads(result)
            for cdn_log_object in result_json['logs']:
                log_file_name = cdn_log_object["name"]
                content = self.get_cdn_log_content(cdn_log_object["link"])
                if content == "":
                    continue
                obj_name = os.path.join(cdn_log_object["domain_name"],
                                        query_date, log_file_name)
                self.put_content_to_obs(obj_name, content)

            total = result_json['total']
            if page_size * page_number >= total:
                break

            page_number += 1
            retry_count = 0

    def put_content_to_obs(self, obj_name, content):
        try:
            resp = self.obs_client.putContent(self.target_bucket,
                                              obj_name, content=content)
            if resp.status > 300:
                self.logger.error(f"failed to put object {obj_name} to "
                                  f"obs bucket {self.target_bucket}, "
                                  f"errorCode:{resp.errorCode} "
                                  f"errorMessage:{resp.errorMessage}")
        except:
            self.logger.error(f"failed to put object {obj_name} to "
                              f"obs bucket {self.target_bucket}, "
                              f"exp:{traceback.format_exc()}")

    def get_cdn_log_content(self, cdn_log_link):
        cdn_log_content = ""
        try:
            cdn_log_url = urlparse(cdn_log_link)
            netlocs = cdn_log_url.netloc.split(":")
            conn = httplib.HTTPConnection(str(netlocs[0]), int(netlocs[1]))
            conn.request('GET', cdn_log_url.path + "?" + cdn_log_url.query)
            cdn_log_content = conn.getresponse()
        except:
            self.logger.error(f"failed to get cdn log from {cdn_log_link} "
                              f"exp:{traceback.format_exc()}")

        return cdn_log_content

    def pull_cdn_logs(self, timestamp, page_number):
        params = {'query_date': timestamp, 'domain_name': self.domainName,
                  'page_size': page_size, 'page_number': page_number,
                  'enterprise_project_id': 'ALL'}
        headers = {'Content-Type': 'application/json;charset=UTF-8',
                   'X-Auth-Token': self.auth_token}
        res = requests.get(self.cdn_log_url, params=params, headers=headers,
                           verify=False)
        if res.status_code != 200:
            self.logger.error("failed to pull cdn logs, urls: %s error: %s ",
                              res.url, res.text)
            return "error"

        return res.text


def new_obs_client(context, obs_server):
    ak = context.getAccessKey()
    sk = context.getSecretKey()
    return ObsClient(access_key_id=ak, secret_access_key=sk, server=obs_server)
